package util.ir;

import java.io.IOException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.RAMDirectory;

import util.models.LanguageModel;
import util.models.Tags;

public class LMSearcherMix  {



	private static String fields_trigrams[] = { "type", "a", "b", "c", "f_t",
		"f_12", "f_23", "f_13", "f_t_b", "f_12_b", "f_23_b", "f_13_b" };

	private static String fields_trigrams_simple[] = { "type", "trigram",
		"f_t", "f_12", "f_23", "f_13", "f_t_b", "f_12_b", "f_23_b",
		"f_13_b" };

	private static String fields_bigrams[] = { "type", "a", "b", "f_b", "f_1",
		"f_2", "f_b_b", "f_1_b", "f_2_b" };
	private static String fields_bigrams_simple[] = { "type", "bigram", "f_b",
		"f_1", "f_2", "f_b_b", "f_1_b", "f_2_b" };
	
	private String index = "";

	private IndexSearcher searcher = null;
	Analyzer analyzer = new WhitespaceAnalyzer();
	
	

	public LMSearcherMix(String index) throws IOException {
		this.index = index;

		RAMDirectory dir = new RAMDirectory(index);
		searcher = new IndexSearcher(dir,true);
		System.out.println("Loaded index into memory");

	}

	
	
	
	public HashSet<String[]> trigramSearchSimple(HashSet<String> ts)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser("trigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + iter.next() + "\t";
		}

		/*
		 * for (int i = 0; i < t.length; i++) {
		 * 
		 * query = query + t[i] + "\t";
		 * 
		 * }
		 */
		query = query.trim();

		// Matching

		Hits hits = searcher.search(queryParser.parse(query));
		HashSet<String[]> response = new HashSet<String[]>();

		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_trigrams_simple.length];
			String temp = "";

			String buffer_b = "";
			boolean matched_right_place = false;
			boolean should_swap = false;

			/**
			 * we are moving the query tags matches to the second position
			 * 
			 */

			for (int j = 0; j < fields_trigrams_simple.length; j++) {
				String value = doc.get(fields_trigrams_simple[j]);

				if (fields_trigrams_simple[j].equals("a")) {
					if (ts.contains(value)) {
						r[j] = value;
					} else {
						r[j] = value;
						buffer_b = value;
						should_swap = true;
					}

				} else if (fields_trigrams_simple[j].equals("c")) {

					if (should_swap) {
						if (ts.contains(value)) {
							r[j - 1] = value;
							r[j] = buffer_b;
							matched_right_place = true;
						} else {

							r[j] = value;
						}

					}

				} else {

					r[j] = value;
				}

				temp = temp + r[j] + "\t";

			}

			if (matched_right_place) {
				response.add(r);
				// System.out.println(temp);
			}
		}

		// swap answers here c for b and b for c
		System.out.println(response.size());
		response.clear();
		searcher.close();
		return response;

	}

	
	/**
	 * 
	 * Modify this to support mode search
	 * 
	 *  
	 * @param ts
	 * @param lm
	 * @param mode
	 * @throws CorruptIndexException
	 * @throws IOException
	 * @throws ParseException
	 */
	
	public void trigramSearchLM(HashSet<String> ts, LanguageModel lm_fore,LanguageModel lm_back,
			String model) throws CorruptIndexException, IOException,
			ParseException {

		QueryParser queryParser = new QueryParser("trigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + QueryParser.escape(iter.next()) + "\t";
		}

		query = query.trim();
		query = query.replace("\t", " OR ");

		query = "(" + query + ") AND (type:" + model + ")";
		// query = "type:adults";
		// Matching
		//query = QueryParser.escape(query);

		//System.out.println(queryParser + "\t" + query + "\t" + searcher);
	
		Hits hits = searcher.search(queryParser.parse(query));

		//System.out.println(hits.length());
		HashSet<String[]> response = new HashSet<String[]>();
		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_trigrams.length - 1];

			boolean matched_right_place = false;

			int index = 0;

			String terms = doc.get(fields_trigrams_simple[1]);

			String terms_s[] = terms.split("\\s+");

			for (int k = 0; k < terms_s.length; k++) {

				r[k] = terms_s[k];
				index++;
			}

			int k=index;
			for (int j = index+1; j < fields_trigrams.length; j++) {
				
				String value = doc.get(fields_trigrams[j]);
			//	System.out.println("index:" +j + "\t"+ fields_trigrams[j] + "\t" + value);
				r[k] = value;
				k++;

			}

			orderFieldsTrigrams(r, ts);

			/*for ( k = 0; k < r.length; k++) {
				System.out.print(r[k] + " ");

			}
			System.out.println("");*/

			response.add(r);

			

			// if (matched_right_place) {
			String temp = "";
			for (int l = 0; l < r.length; l++) {

				temp = temp + r[l] + "\t";
			}
			// System.out.println(matched_right_place + "\t" + temp);

			// System.out.println(temp);
			addTrigramLineToLM(r, lm_fore, lm_back);
			response.add(r);
			// System.out.println(temp);
			// }
		}

	//	System.out.println("Found: " + response.size());
	}

	
	
	/*
	 * Send matched tag to the last position
	 * 
	 */
	
	
	
	
	private boolean orderFieldsTrigrams(String[] r, HashSet<String> ts) {
		// TODO Auto-generated method stub
		
		
		// "type", "a", "b", "c", "f_t",
		// "f_12", "f_23", "f_13", "f_t_b", "f_12_b", "f_23_b", "f_13_b" 
		// kids cool japan yum 1 15 1 1 1 6521 12 21

		// check if match in third position, then no changes needed

		String f_12= r[4];
		String f_23= r[5];
		String f_13= r[6];
		
		String f_12_b= r[8];
		String f_23_b= r[9];
		String f_13_b= r[10];
		
		
		/*for(int i =0; i <r.length; i++){
			
			System.out.println(i+ "\t"+r[i]);
		}*/
		
		if (ts.contains(r[2])) {

			return true;

		} else if (ts.contains(r[0])) {

			// swap 1 and 3 and frequencies
			// a b c   --> c b a 
			String buf = r[0];
			r[0] = r[2];
			r[2] = buf;
			
			// 1 2 changes
			r[4]= f_23; 
			// 2 3 changes
			r[5]= f_12;
			
			//background frequencies
			
			// 1 2 changes
			r[8]= f_23_b; 
			// 2 3 changes
			r[9]= f_12_b;

			return true;

		} else if (ts.contains(r[1])) {
		
			// swap 1 and 3 and frequencies
			//	 a  b  c  -->   a  c  b 
			String buf = r[1];
			r[1] = r[2];
			r[2] = buf;
			
			// 1 2 changes
			r[4]= f_13; 
			// 1 3 changes
			r[6]= f_12;
			
			//background frequencies
			
			// 1 2 changes
			r[8]= f_13_b; 
			// 2 3 changes
			r[10]= f_12_b;

			return true;

		} else {
			return false;

		}

		// check for math in third position

	}

	/**Receives all the t tags 
	 * Return all matching bigrams (matched tag will be put in the first position)
	 * 
	 * 
	 * 
	 * @param ts
	 * @param lm
	 * @throws CorruptIndexException
	 * @throws IOException
	 * @throws ParseException
	 */
	 
	public void bigramSearchLM(HashSet<String> ts, 
			LanguageModel lm_fore, LanguageModel lm_back, String model)
			throws CorruptIndexException, IOException, ParseException {

		QueryParser queryParser = new QueryParser("bigram", analyzer);
		// <default field> is the field that QueryParser will search if you
		// don't
		// prefix it with a field.

		String query = "";

		Iterator<String> iter = ts.iterator();

		while (iter.hasNext()) {

			query = query + QueryParser.escape(iter.next()) + "\t";
		}

		query = query.trim();
		query = query.replace("\t", " OR ");

		query = "(" + query + ") AND (type:" + model + ")";
		
		// Matching
		// System.out.println(queryParser + "\t" + query + "\t"+ searcher);
		Hits hits = searcher.search(queryParser.parse(query));

		HashSet<String[]> response = new HashSet<String[]>();
		//System.out.println("Hits:" + hits.length() + "\tquery:" + query  );
		
		
		for (int i = 0; i < hits.length(); i++) {

			Document doc = hits.doc(i);

			String r[] = new String[fields_bigrams.length - 1];

			// boolean matched_right_place = false;

			int index = 0;

			String terms = doc.get(fields_bigrams_simple[1]);

			String terms_s[] = terms.split("\\s+");

			for (int k = 0; k < terms_s.length; k++) {

				r[k] = terms_s[k];
				index++;
			}

			int k = index;
			for (int j = index+1; j < fields_bigrams.length; j++) {

				String value = doc.get(fields_bigrams[j]);
				//System.out.println("k:" + k + "\t"  + value + "\t"+ fields_bigrams[j]);
				r[k] = value;
				k++;

			}
			
		
			orderFieldsBigrams(r, ts);

			

			response.add(r);
			/*
			 * For now, revized this!!!!!!!!!!
			 */

			// System.out.println(matched_right_place + "\t" + terms);
			// if (matched_right_place) {
			String temp = "";
			for (int l = 0; l < r.length; l++) {

				temp = temp + r[l] + "\t";
			}

			// System.out.println(temp);
			addBigramLineToLM(r, lm_fore, lm_back);

			// System.out.println(temp);
			// }
		}

	//	System.out.println("Found: " + response.size());
		response.clear();

	}

	
	
	
	
	
	
	
	
	
/**
 * matching position is the first position, againts the tag queries
 * 
 * Position zero is for s, position 1 is for query tag
 * 	
 * @param r
 * @param ts
 * @return
 */
	private static boolean orderFieldsBigrams(String[] r, HashSet<String> ts) {
		// TODO Auto-generated method stub

		//  "type", "a", "b", "f_b",
		//  "f_1", "f_2", "f_b_b", "f_1_1", "f_2_1" }

		// check if match in second position, then no changes needed

		if (ts.contains(r[1])) {
		
			return true;
			
		} else if (ts.contains(r[0])) {
		
			// swap a and b and frequencies
			
			String buf = r[0];
			r[0] = r[1];
			r[1] = buf;

			buf = r[3];
			r[3] = r[4];
			r[4] = buf;
			
			// background frequencies
			
			buf = r[6];
			
			r[6] = r[7];
			
			r[7] = buf;
			
			
			
		
			return true;

		} else {

			return false;
		}

		// check for math in third position

		

	}
	
	// swap answers here c for b and b for c

	// searcher.close();

	


	public void close() {

		try {
			searcher.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void addTrigramLineToLM(String[] r, LanguageModel lm_fore, LanguageModel lm_back) {
		// TODO Auto-generated method stub

		
		//kids cool japan yum 1 15 1 1 1 6521 12 21
		String k = r[1];
		String s = r[0];
		String t = r[2];
		// { "a", "b", "c", "f_t", "f_seed","f_12", "f_23", "f_13" };

				
		Integer freq_t = Integer.valueOf(r[3]);
		Integer freq_ks = Integer.valueOf(r[4]);
		Integer freq_st = Integer.valueOf(r[5]);
		Integer freq_kt = Integer.valueOf(r[6]);
		
		lm_fore.addTrigram(s, k, t, freq_t);

		lm_fore.addBigram(s, k, freq_ks);
		lm_fore.addBigram(s, t, freq_st);
		lm_fore.addBigram(k, t, freq_kt);

		
		//agoogle translationding background frequencies
		
		Integer freq_t_b = Integer.valueOf(r[7]);
		Integer freq_ks_b = Integer.valueOf(r[8]);
		Integer freq_st_b = Integer.valueOf(r[9]);
		Integer freq_kt_b = Integer.valueOf(r[10]);
		
	//freq_t_b = freq_t_b - freq_t;
		//freq_ks_b = freq_ks_b -freq_ks;
	//	freq_st_b = freq_st_b -freq_st;
		//freq_kt_b = freq_kt_b -freq_kt;
		
		
		if(freq_t_b<=0 ){
			
			freq_t_b=1;
		}
		
		if(freq_ks_b<=0){
			
			
			freq_ks_b=1;
			
		} 
		if(freq_st_b<=0){
			
			freq_st_b=1;
			
		}
		
		if(freq_kt_b<=0){
			
			freq_kt_b=1;
		}
		
		lm_back.addTrigram(s, k, t, freq_t_b);

		lm_back.addBigram(s, k, freq_ks_b);
		lm_back.addBigram(s, t, freq_st_b);
		lm_back.addBigram(k, t, freq_kt_b);

		
		// add unigrams

		//lm.addUnigram(k, freq_seed);
		
		//lm.seeds.put(k, Float.valueOf(freq_seed));

	}

	private void addBigramLineToLM(String[] r, LanguageModel lm_fore,
			LanguageModel lm_back) {
		// TODO Auto-generated method stub

		String s = r[0];
		String t = r[1];

		
	//	System.out.println("adding "  + s + "\t" + t);
		
		// adults
		/*
		 * ---area117901261312125
		 */

		Integer freq_b = Integer.valueOf(r[2]);
		Integer freq_s = Integer.valueOf(r[3]);
		Integer freq_t = Integer.valueOf(r[4]);

		lm_fore.addBigram(s, t, freq_b);
		lm_fore.addUnigram(t, freq_t);
		lm_fore.addUnigram(s, freq_s);

		// background stats
		Integer freq_b_b = Integer.valueOf(r[5]);
		Integer freq_s_b = Integer.valueOf(r[6]);
		Integer freq_t_b = Integer.valueOf(r[7]);

	//	System.out.println("Before substaction " + "\t" + s + "\t" + t);
		//System.out.println("freq_q:\t" + freq_b_b + "\t" + freq_b);
	//	System.out.println("freq_t:\t" + freq_t_b + "\t" + freq_t);
	//	System.out.println("freq_s:\t" + freq_s_b + "\t" + freq_s);

		// discount children counts in global counts
	//	freq_b_b = freq_b_b - freq_b;
	///	freq_s_b = freq_s_b - freq_s;
	//	freq_t_b = freq_t_b - freq_t;

		if (freq_b_b <= 0){
			freq_b_b=1;
			
		}
		
		
		if(freq_s_b<=0){
			
			freq_s_b=1;
			
		}
		
		if(freq_t_b<=0){
			freq_t=1;
			
			
		}
				

		lm_back.addBigram(s, t, freq_b_b);
		lm_back.addUnigram(t, freq_t_b);
		lm_back.addUnigram(s, freq_s_b);
		
		
		// adding candidate tags
		lm_fore.candidates.add(s);
		lm_fore.candidates.add(t);

		lm_back.candidates.add(s);
		lm_back.candidates.add(t);

		// add unigrams
		// lm.addUnigram(k, freq_seed);
		// lm.seeds.put(k, Float.valueOf(freq_seed));

	}

	public static void main(String args[]) throws ParseException {

		/*
		 * try { LMSearcher lm = new LMSearcher(
		 * "/home/sergio/delicious_index/trigrams_index_filter2");
		 * 
		 * HashSet<String> query = new HashSet<String>();
		 * 
		 * query.add("games"); query.add("toys"); query.add("flash");
		 * query.add("kids");
		 * 
		 * LanguageModel lmodel = new LanguageModel(); lm.trigramSearchLM(query,
		 * lmodel);
		 * 
		 * } catch (IOException e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */
		String path = "/home/sergio/delicious_index/bigrams_index_mix";
	
		try {
			LMSearcherMix lm = new LMSearcherMix(
					path);

			HashSet<String> query = new HashSet<String>();
		
			query.add("religion");

			LanguageModel lmodel_fore = new LanguageModel();
			LanguageModel lmodel_back = new LanguageModel();
			lm.bigramSearchLM(query, lmodel_fore, lmodel_back,"kids-teens-mteens");
			System.out.println(lmodel_fore.unigrams.size() + "\t"+ lmodel_fore.unigrams.size() );

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
